package com.dyb.idempotent.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

/**
 * @ProjectName: idempotent
 * @Package: com.dyb.idempotent.service
 * @ClassName: RedisService
 * @Author: Deng YuBin
 * @Description:
 * @Date: 2021/1/14 16:34
 * @Version: 1.0
 */
@Service
public class RedisService {

    @Autowired
    private ShardedJedisPool shardedJedisPool;

    private <T> T execute(Function<T, ShardedJedis> fun) {
        ShardedJedis shardedJedis = null;
        try {
            // 从连接池中获取到jedis分片对象
            shardedJedis = shardedJedisPool.getResource();
            return fun.callback(shardedJedis);
        } finally {
            if (null != shardedJedis) {
                // 关闭，检测连接是否有效，有效则放回到连接池中，无效则重置状态
                shardedJedis.close();
            }
        }
    }

    /**
     * 定义一个方法传入接口类，调用该接口类中的接口
     *
     * @param fun
     * @param <T>
     * @return
     */
    private <T> T executeTest(TestFunction<T,String> fun){
        return fun.test("我会先执行");
    }

    /**
     * 执行set操作
     *
     * @param key
     * @param value
     * @return
     */
    public String set(final String key, final String value) {
        return this.execute(e -> e.set(key, value));
    }

    /**
     * 执行get操作
     *
     * @param key
     * @return
     */
    public String get(final String key) {
        return this.execute(e -> e.get(key));
    }

    /**
     * 执行删除操作
     *
     * @param key
     * @return
     */
    public Long del(final String key) {
        return this.execute(e -> e.del(key));
    }

    /**
     * 设置生存时间，单位为：秒
     *
     * @param key
     * @param seconds
     * @return
     */
    public Long expire(final String key, final Integer seconds) {
        return this.execute(e -> e.expire(key, seconds));
    }

    /**
     * 执行set操作并且设置生存时间，单位为：秒
     *
     * @param key
     * @param value
     * @return
     */
    public String set(final String key, final String value, final Integer seconds) {
        return this.execute(e -> {
            String str = e.set(key, value);
            e.expire(key, seconds);
            return str;
        });
    }

    /**
     * 定义方法调用私有方法，
     *
     * @param key
     * @return
     */
    public String see(String key){
       return this.executeTest(new TestFunction<String, String>() {
            @Override
            public String test(String s) {
                return s+"我会后执行吗？";
            }
        });

    }
}
